﻿package znet

import (
	"fmt"
	"net"
	"zxGoServer/zinterface"
)

type Server struct {
	zinterface.IServer

	Name     string
	IPVerion string

	IP   string
	Port int
	//当前Server的链接[connection]管理器
	ConnMgr zinterface.IConManager

	//该Server的连接创建时Hook函数
	OnConnStart func(conn zinterface.IConnection)
	//该Server的连接断开时的Hook函数
	OnConnStop func(conn zinterface.IConnection)
}

func NewServer() zinterface.IServer {
	s := &Server{
		Name:     "server",
		IPVerion: "tcp4",
		IP:       "0.0.0.0",
		Port:     8099,
		ConnMgr:  NewConnManager(),
	}
	return s
}

func (s *Server) Start() {
	fmt.Printf("[START] Server name: %s,listenner at IP: %s, Port %d is starting\n\n", s.Name, s.IP, s.Port)

	go func() {

		// 获取一个TCP的addr
		addr, err := net.ResolveTCPAddr(s.IPVerion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			fmt.Printf("[START] ResolveTCPAddr err: %s\n", err)
			return
		}

		// 监听服务器地址
		listener, err := net.ListenTCP(s.IPVerion, addr)
		if err != nil {
			fmt.Printf("[START] ListenTCP err: %s\n", err)
			return
		}

		//
		fmt.Printf("[START] ListenTCP %s now listening\n", s.Name)

		var cid uint32
		cid = 0

		for {
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Printf("[START] AcceptTCP err: %s\n", err)
				continue
			}
			fmt.Printf("[START] AcceptTCP %s now connecting\n", conn.RemoteAddr().String())

			connection := NewConnection(s, NewNetTcpConn(conn), cid)
			cid++

			go connection.Start()
		}
	}()
}

func (s *Server) Stop() {
	fmt.Println("[Stop] Server stop", s.Name)

	s.ConnMgr.ClearConn()
}

func (s *Server) Serve() {
	s.Start()

	//阻塞,否则主Go退出， listenner的go将会退出
	select {}
}

func (s *Server) GetConnMgr() zinterface.IConManager {
	return s.ConnMgr
}

func (s *Server) SetOnConnStart(hookFunc func(connection zinterface.IConnection)) {
	s.OnConnStart = hookFunc
}

func (s *Server) SetOnConnStop(hookFunc func(connection zinterface.IConnection)) {
	s.OnConnStop = hookFunc
}

func (s *Server) CallOnConnStart(conn zinterface.IConnection) {
	if s.OnConnStart != nil {
		s.OnConnStart(conn)
	}
}

func (s *Server) CallOnConnStop(conn zinterface.IConnection) {
	if s.OnConnStop != nil {
		s.OnConnStop(conn)
	}
}
